#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "json.h"

typedef struct{
    char *value_string;
    int value_int;
    double value_double;
    data_type type;
}json_data;

typedef struct _json_node{
    struct _json_node *next, *prev, *child;
    char *key;
    json_data *value;
}json_handler;

/**
 * @brief 打印number个tab
 * 
 * @param number 
 */
static void print_tab(int number) {
    int i;
    for(i = 0; i < number; i++) {
        printf("\t");
    }
}

/**
 * @brief 创建一个jsondata数据
 * 
 * @param data 数据，需要传入地址，如果是字符串则必须末尾带'\0'
 * @param type 指定数据的类型
 * @return 成功返回json_data格式数据，失败返回NULL
 */
static json_data *json_data_create(void *data, data_type type) {
    json_data *create_data = (json_data *)malloc(sizeof(json_data));
    int len = 0;
    if(create_data == NULL) {
        return NULL;
    }
    create_data->value_string = NULL;
    create_data->value_int = 0;
    create_data->value_double = 0;

    if(data == NULL) {
        free(create_data);
        return NULL;
    }

    switch (type)
    {
    case JSON_STRING:
        len = strlen((char *)data) + 1;
        create_data->value_string = (char *)malloc(sizeof(char) * len);
        if(create_data->value_string == NULL) {
            free(create_data);
            return NULL;
        }
        memset(create_data->value_string, 0, len);
        strcpy(create_data->value_string, (char *)data);
        break;

    case JSON_INT:
        create_data->value_int = (*(int*)data);
        break;

    case JSON_DOUBLE:
        create_data->value_double = (*(double *)data);
        break;

    default:
        free(create_data);
        return NULL;
    }
    create_data->type = type;
    return create_data;
}

/**
 * @brief 释放json data内容，释放后自动置空
 * 
 * @param data 
 */
static void json_data_delete(json_data **data) {
    if((*data)->value_string != NULL) {
        free((*data)->value_string);
    }
    free(*data);
    *data = NULL;
}

int json_add_data(json_handler **handler, const char *key, void *data, data_type type) {
    json_handler *temp = (json_handler *)malloc(sizeof(json_handler));
    json_handler *root = NULL;
    int len = 0;
    if(temp == NULL) {
        return JSON_ERR_MALLOC;
    }
    if(data == NULL || type > JSON_DOUBLE || key == NULL) {
        free(temp);
        return JSON_ERR_BAD_INPUT;
    }
    temp->child = NULL;
    temp->next = NULL;
    temp->prev = NULL;

    len = strlen(key);
    temp->key = (char *)malloc(sizeof(char) * (len + 1));
    if(temp->key == NULL) {
        free(temp);
        return JSON_ERR_MALLOC;
    }
    memset(temp->key, 0, len + 1);
    strcpy(temp->key, key);

    printf("key = %s\n", temp->key);

    temp->value = json_data_create(data, type);
    if(temp->value == NULL) {
        free(temp);
        return JSON_ERR_CREATE_DATA;
    }
    
    if(*handler == NULL) {
        *handler = temp;
        return JSON_OK;
    }
    else {
        root = *handler;
        while(root->next != NULL) {
            root = root->next;
        }
        root->next = temp;
        temp->prev = root;
        return JSON_OK;
    }
}

int json_add_child(json_handler **handler, const char *key, json_handler *child_value) {
    json_handler *root = *handler;
    json_handler *temp = NULL;
    int len = 0;
    if(key == NULL || child_value == NULL) {
        return JSON_ERR_BAD_INPUT;
    }

    temp = (json_handler *)malloc(sizeof(json_handler));
    if(temp == NULL) {
        return JSON_ERR_MALLOC;
    }
    temp->child = child_value;
    
    len = strlen(key) + 1;
    temp->key = (char *)malloc(sizeof(char) * len);
    if(temp->key == NULL) {
        free(temp);
        return JSON_ERR_MALLOC;
    }
    memset(temp->key, 0, len);
    strcpy(temp->key, key);
    
    temp->next = NULL;
    temp->prev = NULL;
    temp->value = NULL;

    if(*handler == NULL) {
        *handler = temp;
        return JSON_OK;
    }

    while(root->next != NULL) {
        root = root->next;
    }
    root->next = temp;
    temp->next = NULL;
    temp->prev = root;

    return JSON_OK;
}

void json_free_all(json_handler **handler) {
    json_handler *root = *handler;
    json_handler *temp = NULL;
    if(root == NULL) {
        return;
    }
    while(root != NULL) {
        if(root->value != NULL) {
            free(root->value);
        }
        if(root->key != NULL) {
            free(root->key);
        }
        if(root->value != NULL) {
            json_data_delete(&root->value);
        }
        if(root->child != NULL) {   // 先释放孩子节点
            json_free_all(&root->child);
        }
        temp = root;
        root = root->next;
        free(temp);
    }
    *handler = NULL;
}

void json_print(json_handler *handler) {

    typedef struct {
        json_handler *handler;
        int level;
    }stack;

    json_handler *now = NULL;
    int level = 0;
    int top = 0;
    stack s[1024] = { 0 };

    s[0].handler = handler;
    s[0].level = 1;
    top = 1;

    printf("{\n");
    while(top != 0) {
        now = s[top - 1].handler;
        level = s[top - 1].level;
        top--;
        
        // 先判断是否孩子节点结束
        if(now == NULL) {
            print_tab(level);
            printf("}\n");
            continue;
        }
        
        // 打印key
        print_tab(level);
        printf("\"%s\": ", now->key);

        // 先入栈next节点
        if(now->next != NULL) {
            s[top].handler = now->next;
            s[top].level = level;
            top++;
        }

        // 如果存在孩子节点则入栈，因为孩子节点并不是value，所以进行下一次循环
        if(now->child != NULL) {
            printf("\b{\n");
            s[top].handler = NULL;
            s[top].level = level + 1;
            top++;
            s[top].handler = now->child;
            s[top].level = level + 2;
            top++;
            continue;
        }

        // 打印value
        if(now->value != NULL) {
            switch (now->value->type)
            {
            case JSON_STRING:
                printf("\"%s\"\n", now->value->value_string);
                break;
            case JSON_INT:
                printf("\"%d\"\n", now->value->value_int);
                break;
            case JSON_DOUBLE:
                printf("\"%.6lf\"\n", now->value->value_double);
                break;
            }
        }
    }
    printf("}\n");
}

/**
 * @brief json解析
 * 
 * @note 实现思想如下：
 * 1. 过滤掉无关字符并进行括号统计
 * 2. 声明一个队列:
 * typedef enum {
 *      JSON_TYPE_NEXT
 *      JSON_TYPE_CHILD
 * }json_type;
 * 
 * typedef struct {
 *      json_handler *node;
 *      json_type type;
 * }queue;
 * 3. 读取key
 * 4. 读取后一个字符，如果是'{'则证明是孩子节点，其他则为next节点
 * 5. 将读取后的入队
 * 6. 重复4、5直到解析完成
 * 
 * @param handler 
 * @param in 
 * @return int 
 */
int json_parse(json_handler **handler, const char *in) {
    int len = 0, i, counter = 0, left = 0;
    char *ans = NULL;
    if(handler == NULL || in == NULL) {
        return JSON_ERR_BAD_INPUT;
    }
    len = strlen(in) + 1;
    ans = (char *)malloc(sizeof(char) * len);

    // 过滤掉空格、回车，查看括号是否匹配
    for(i = 0; i < len; i++) {
        if(in[i] == ' ' || in[i] == '\n') {
            continue;
        }
        if(in[i] == '{') {
            left++;
        }
        if(in[i] == '}') {
            left--;
        }
        if(left < 0) {
            return JSON_ERR_BAD_JSON;
        }
        ans[counter] = in[i];
        counter++;
    }
    ans[counter] = '\0';
    if(left != 0) {
        return JSON_ERR_BAD_JSON;
    }

    printf("%s\n", ans);

    free(ans);
}

void json_debug_print_all(json_handler *handler) {

    typedef struct {
        json_handler *handler;
        int level;
    }stack;

    json_handler *now = NULL;
    int level = 0;
    stack s[1024] = { 0 };  // 按照先入栈next，再入栈孩子的顺序进行操作
    int counter = 1;    // counter永远指向下一个要插入的位置
    s[0].handler = handler;
    s[0].level = 0;
    printf("{\n");
    while(counter != 0) {
        // 出栈，获得当前节点，并top--
        now = s[counter - 1].handler;
        level = s[counter - 1].level;
        counter--;

        for(int i = 0; i < level; i++) {
            printf("\t");
        }
        printf("\"%s\": ", now->key);
        if(now->child == NULL) {
            switch (now->value->type)
            {
                case JSON_STRING:
                    printf("\"%s\",\n", now->value->value_string);
                    break;
                case JSON_INT:
                    printf("\"%d\",\n", now->value->value_int);
                    break;
                case JSON_DOUBLE:
                    printf("\"%lf\",\n", now->value->value_double);
                    break;
            }
        }
        else {
            printf("\n{");
        }

        if(now->next == NULL) {
            if(counter != 0) {
                if(level > s[counter - 1].level) {
                    printf("}\n");
                }
            }
            else if (level != 0) {
                for(int i = 0; i < level; i++) {
                    printf("}\n");
                }
            }
        }

        if(now->next != NULL) {
            s[counter].handler = now->next;
            s[counter].level = level;
            counter++;
        }
        if(now->child != NULL) {
            s[counter].handler = now->child;
            s[counter].level = level + 1;
            counter++;
        }
    }
    printf("}\n");
}